type unionFind struct {
	p, size []int
}

func newUnionFind(n int) *unionFind {
	p := make([]int, n)
	size := make([]int, n)
	for i := range p {
		p[i] = i
		size[i] = 1
	}
	return &unionFind{p, size}
}

func (uf *unionFind) find(x int) int {
	if uf.p[x] != x {
		uf.p[x] = uf.find(uf.p[x])
	}
	return uf.p[x]
}

func (uf *unionFind) union(a, b int) bool {
	pa, pb := uf.find(a), uf.find(b)
	if pa == pb {
		return false
	}
	if uf.size[pa] > uf.size[pb] {
		uf.p[pb] = pa
		uf.size[pa] += uf.size[pb]
	} else {
		uf.p[pa] = pb
		uf.size[pb] += uf.size[pa]
	}
	return true
}

func (uf *unionFind) getSize(root int) int {
	return uf.size[root]
}

func minMalwareSpread(graph [][]int, initial []int) int {
	n := len(graph)
	uf := newUnionFind(n)
	for i := range graph {
		for j := i + 1; j < n; j++ {
			if graph[i][j] == 1 {
				uf.union(i, j)
			}
		}
	}
	cnt := make([]int, n)
	ans, mx := n, 0
	for _, x := range initial {
		cnt[uf.find(x)]++
	}
	for _, x := range initial {
		root := uf.find(x)
		if cnt[root] == 1 {
			sz := uf.getSize(root)
			if sz > mx || sz == mx && x < ans {
				ans, mx = x, sz
			}
		}
	}
	if ans == n {
		return slices.Min(initial)
	}
	return ans
}